package com.lib.common.view.ui;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.IntDef;

import com.lib.common.R;
import com.lib.utils.XLog;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * 网格流式布局 - 支持流式布局和网格布局两种模式
 * 功能特性：
 * 1. 当items_per_row=0时为流式布局，自动换行
 * 2. 当items_per_row>0时为网格布局，固定列数
 */
public class GridFlowLayout extends ViewGroup {
    // 边距模式注解
    @IntDef({MarginMode.AUTO, MarginMode.FIXED})
    @Retention(RetentionPolicy.SOURCE)
    public @interface MarginMode {
        int AUTO = 0;    // 自动计算边距
        int FIXED = 1;   // 固定边距
    }

    // 布局属性值
    private int mItemsPerRow = 3;                    // 每行项目数，0表示流式布局
    @MarginMode
    private int mMarginMode = MarginMode.AUTO;       // 边距模式
    private float mItemMarginLeft = 0;               // 项目左边距
    private float mItemMarginRight = 0;              // 项目右边距
    private float mRowSpacing = 0;                   // 行间距

    public GridFlowLayout(Context context) {
        super(context);
        init(context, null);
    }

    public GridFlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public GridFlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    /**
     * 初始化布局属性
     */
    private void init(Context context, AttributeSet attrs) {
        XLog.i("GridFlowLayout init");
        if (attrs != null) {
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.GridFlowLayout);
            mItemsPerRow = ta.getInt(R.styleable.GridFlowLayout_items_per_row, 3);
            mMarginMode = ta.getInt(R.styleable.GridFlowLayout_margin_mode, MarginMode.FIXED);
            mItemMarginLeft = ta.getDimension(R.styleable.GridFlowLayout_item_margin_left, 0);
            mItemMarginRight = ta.getDimension(R.styleable.GridFlowLayout_item_margin_right, 0);
            mRowSpacing = ta.getDimension(R.styleable.GridFlowLayout_row_spacing, 0);
            ta.recycle();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int childCount = getChildCount();
        if (childCount == 0) {
            // 没有子View时使用默认测量
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }

        // 根据模式选择不同的测量策略
        if (mItemsPerRow == 0) {
            measureFlowLayout(widthMeasureSpec, heightMeasureSpec);
        } else {
            measureGridLayout(widthMeasureSpec, heightMeasureSpec);
        }
    }

    /**
     * 测量流式布局
     */
    private void measureFlowLayout(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int paddingLeft = getPaddingLeft();
        int paddingRight = getPaddingRight();
        int paddingTop = getPaddingTop();
        int paddingBottom = getPaddingBottom();

        int availableWidth = widthSize - paddingLeft - paddingRight;
        int currentLeft = paddingLeft;
        int currentTop = paddingTop;
        int currentLineHeight = 0;
        int childCount = getChildCount();
        boolean hasContentInCurrentLine = false;
        boolean lastWasMatchParent = false; // 新增：标记上一个是否是match_parent

        // 进行布局计算
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            if (child.getVisibility() == GONE) {
                continue;
            }
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);

            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();

            // 计算包含margin的尺寸
            int childWidthWithMargin = childWidth + lp.leftMargin + lp.rightMargin;
            int childHeightWithMargin = childHeight + lp.topMargin + lp.bottomMargin;

            // 检查是否需要换行（包括上一个是否是match_parent的情况）
            boolean needWrap = false;

            if (lp.width == LayoutParams.MATCH_PARENT) {
                // MATCH_PARENT的特殊处理
                int remainingWidth = widthSize - currentLeft - paddingRight;
                int minWidth = getChildMinWidth(child, lp);

                if (lastWasMatchParent) {// 上一个就是match_parent，则需要换行
                    needWrap = true;
                } else if (hasContentInCurrentLine && (remainingWidth < minWidth + lp.leftMargin + lp.rightMargin)) {
                    // 如果剩余空间不足
                    needWrap = true;
                }

                if (needWrap) {// 换行
                    currentTop += currentLineHeight + mRowSpacing;
                    currentLeft = paddingLeft;
                    currentLineHeight = 0;
                    hasContentInCurrentLine = false;
                    lastWasMatchParent = false;
                }

                // 测量MATCH_PARENT的子View
                if (!hasContentInCurrentLine) {
                    // 新的一行：占满整行
                    childWidth = Math.max(minWidth, availableWidth - lp.leftMargin - lp.rightMargin);
                } else {
                    // 当前行已有内容：占满剩余空间
                    childWidth = Math.max(minWidth, remainingWidth - lp.leftMargin - lp.rightMargin);
                }

                // 重新测量子View
                int widthSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY);
                int heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
                measureChildWithMargins(child, widthSpec, 0, heightSpec, 0);

                childWidthWithMargin = childWidth + lp.leftMargin + lp.rightMargin;
                childHeightWithMargin = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;

                // 标记当前是match_parent
                lastWasMatchParent = true;
            } else {
                // 如果上一个子View是match_parent，当前普通子View必须换行
                if (lastWasMatchParent) {
                    needWrap = true;
                } else {
                    // 普通子View的处理
                    needWrap = hasContentInCurrentLine && (currentLeft + childWidthWithMargin) > (widthSize - paddingRight);
                }

                if (needWrap && hasContentInCurrentLine) {
                    currentTop += currentLineHeight + mRowSpacing;
                    currentLeft = paddingLeft;
                    currentLineHeight = 0;
                    hasContentInCurrentLine = false;
                }

                // 重置标记
                lastWasMatchParent = false;
            }

            // 更新位置信息
            currentLeft += childWidthWithMargin;
            currentLineHeight = Math.max(currentLineHeight, childHeightWithMargin);
            hasContentInCurrentLine = true;
        }

        // 计算总高度并设置测量尺寸
        int totalHeight = currentTop + currentLineHeight + paddingBottom;
        totalHeight = Math.max(totalHeight, getSuggestedMinimumHeight());
        setMeasuredDimension(
                resolveSize(widthSize, widthMeasureSpec),
                resolveSize(totalHeight, heightMeasureSpec)
        );
    }

    /**
     * 测量网格布局
     */
    private void measureGridLayout(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int paddingLeft = getPaddingLeft();
        int paddingRight = getPaddingRight();
        int paddingTop = getPaddingTop();
        int paddingBottom = getPaddingBottom();

        int availableWidth = widthSize - paddingLeft - paddingRight;
        int childCount = getChildCount();

        // 修复：处理items_per_row大于子View数量的情况
        int actualItemsPerRow = Math.min(mItemsPerRow, childCount);
        if (actualItemsPerRow <= 0) {
            actualItemsPerRow = 1; // 确保至少有一列
        }

        // 计算网格参数（修复边距计算）
        GridLayoutParams gridParams = calculateGridParams(availableWidth, actualItemsPerRow);
        int itemWidthPx = gridParams.itemWidth;
        int marginLeftPx = gridParams.marginLeft;
        int marginRightPx = gridParams.marginRight;

        // 测量所有子View
        int currentRowHeight = 0;
        int totalHeight = paddingTop;
        int currentRowItemCount = 0;

        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            if (child.getVisibility() == GONE) {
                continue;
            }

            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();

            // 计算子View的测量规格
            MeasureSpecs specs = calculateChildMeasureSpecs(child, lp, itemWidthPx);

            // 测量子View
            measureChildWithMargins(child, specs.widthSpec, 0, specs.heightSpec, 0);

            int childHeightWithMargin = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
            currentRowHeight = Math.max(currentRowHeight, childHeightWithMargin);
            currentRowItemCount++;

            // 换行处理
            if (currentRowItemCount == actualItemsPerRow || i == childCount - 1) {
                totalHeight += currentRowHeight;
                if (i < childCount - 1) { // 最后一行不加行间距
                    totalHeight += mRowSpacing;
                }
                currentRowHeight = 0;
                currentRowItemCount = 0;
            }
        }

        totalHeight += paddingBottom;
        totalHeight = Math.max(totalHeight, getSuggestedMinimumHeight());
        setMeasuredDimension(
                resolveSize(widthSize, widthMeasureSpec),
                resolveSize(totalHeight, heightMeasureSpec)
        );
    }


    /**
     * 计算网格布局参数
     */
    private GridLayoutParams calculateGridParams(int availableWidth, int itemsPerRow) {
        float marginLeft, marginRight, itemWidth;

        if (mMarginMode == MarginMode.AUTO) {
            // 自动模式：总边距为可用宽度的10%
            float totalMargin = availableWidth * 0.1f;
            marginLeft = totalMargin / (itemsPerRow * 2);
            marginRight = marginLeft;
        } else {
            // 固定模式：使用设定的边距值
            marginLeft = mItemMarginLeft;
            marginRight = mItemMarginRight;
        }

        // 计算项目宽度（修复：确保不为负数）
        float totalHorizontalMargin = (marginLeft + marginRight) * itemsPerRow;
        itemWidth = Math.max(0, (availableWidth - totalHorizontalMargin) / itemsPerRow);

        return new GridLayoutParams(Math.round(itemWidth), Math.round(marginLeft), Math.round(marginRight));
    }

    /**
     * 计算子View的测量规格
     */
    private MeasureSpecs calculateChildMeasureSpecs(View child, MarginLayoutParams lp, int availableWidth) {
        int widthSpecMode = MeasureSpec.EXACTLY;
        int widthSpecSize = availableWidth;

        if (lp.width == LayoutParams.WRAP_CONTENT) {
            widthSpecMode = MeasureSpec.AT_MOST;
            widthSpecSize = availableWidth;
        } else if (lp.width == LayoutParams.MATCH_PARENT) {
            widthSpecMode = MeasureSpec.EXACTLY;
            widthSpecSize = availableWidth;
        } else if (lp.width > 0) {
            widthSpecMode = MeasureSpec.EXACTLY;
            widthSpecSize = Math.min(lp.width, availableWidth);
        }

        // 处理minWidth约束
        int minWidth = getChildMinWidth(child, lp);
        if (widthSpecSize < minWidth) {
            widthSpecSize = minWidth;
        }

        int heightSpecMode = MeasureSpec.UNSPECIFIED;
        if (lp.height == LayoutParams.MATCH_PARENT) {
            heightSpecMode = MeasureSpec.AT_MOST;
        } else if (lp.height > 0) {
            heightSpecMode = MeasureSpec.EXACTLY;
        }

        return new MeasureSpecs(
                MeasureSpec.makeMeasureSpec(widthSpecSize, widthSpecMode),
                MeasureSpec.makeMeasureSpec(0, heightSpecMode)
        );
    }

    /**
     * 获取子View的最小宽度
     */
    private int getChildMinWidth(View child, MarginLayoutParams lp) {
        int minWidth = 0;
        // 检查android:minWidth属性
        if (child.getMinimumWidth() > 0) {
            minWidth = child.getMinimumWidth();
        }
        // 确保不超过父容器限制
        if (lp.width > 0) {
            minWidth = Math.min(minWidth, lp.width);
        }
        return minWidth;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        if (childCount == 0) return;

        if (mItemsPerRow == 0) {
            layoutFlowLayout();
        } else {
            layoutGridLayout();
        }
    }

    /**
     * 流式布局排列
     */
    private void layoutFlowLayout() {
        int width = getWidth();
        int paddingLeft = getPaddingLeft();
        int paddingTop = getPaddingTop();
        int paddingRight = getPaddingRight();

        int currentLeft = paddingLeft;
        int currentTop = paddingTop;
        int currentLineHeight = 0;
        int childCount = getChildCount();
        boolean hasContentInCurrentLine = false;
        boolean lastWasMatchParent = false; // 新增：标记上一个是否是match_parent

        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            if (child.getVisibility() == GONE) {
                continue;
            }

            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();

            // 计算包含margin的宽度
            int childWidthWithMargin = childWidth + lp.leftMargin + lp.rightMargin;

            // 检查是否需要换行
            boolean needWrap = false;

            if (lp.width == LayoutParams.MATCH_PARENT) {
                int remainingWidth = width - currentLeft - paddingRight;
                int minWidth = getChildMinWidth(child, lp);

                if (lastWasMatchParent) {
                    /* 上一个就是match_parent，则需要换行 */
                    needWrap = true;
                } else if (hasContentInCurrentLine && remainingWidth < minWidth + lp.leftMargin + lp.rightMargin) {
                    needWrap = true;
                }

                if (needWrap) {
                    currentTop += currentLineHeight + mRowSpacing;
                    currentLeft = paddingLeft;
                    currentLineHeight = 0;
                    hasContentInCurrentLine = false;
                    lastWasMatchParent = false;
                    // 重新计算剩余宽度
                    remainingWidth = width - paddingLeft - paddingRight;
                }

                // 确定最终宽度
                if (!hasContentInCurrentLine) {
                    // 新的一行：占满整行
                    childWidth = Math.max(minWidth, width - paddingLeft - paddingRight - lp.leftMargin - lp.rightMargin);
                } else {
                    // 当前行已有内容：占满剩余空间
                    childWidth = Math.max(minWidth, remainingWidth - lp.leftMargin - lp.rightMargin);
                }
                childWidthWithMargin = childWidth + lp.leftMargin + lp.rightMargin;

                // 标记当前是match_parent
                lastWasMatchParent = true;

            } else {
                // 如果上一个子View是match_parent，当前普通子View必须换行
                if (lastWasMatchParent) {
                    needWrap = true;
                } else {
                    // 普通子View的换行检查
                    needWrap = hasContentInCurrentLine && (currentLeft + childWidthWithMargin) > (width - paddingRight);
                }

                if (needWrap && hasContentInCurrentLine) {
                    currentTop += currentLineHeight + mRowSpacing;
                    currentLeft = paddingLeft;
                    currentLineHeight = 0;
                    hasContentInCurrentLine = false;
                }

                // 重置标记
                lastWasMatchParent = false;
            }

            // 布局子View
            int childLeft = currentLeft + lp.leftMargin;
            int childTop = currentTop + lp.topMargin;
            child.layout(childLeft, childTop,
                    childLeft + childWidth, childTop + childHeight);

            // 更新位置信息
            currentLeft += childWidthWithMargin;
            currentLineHeight = Math.max(currentLineHeight, childHeight + lp.topMargin + lp.bottomMargin);
            hasContentInCurrentLine = true;
        }
    }

    /**
     * 网格布局排列
     */
    private void layoutGridLayout() {
        int width = getWidth();
        int paddingLeft = getPaddingLeft();
        int paddingTop = getPaddingTop();
        int paddingRight = getPaddingRight();
        int childCount = getChildCount();

        // 计算实际列数（修复：处理列数大于子View数量的情况）
        int actualItemsPerRow = Math.min(mItemsPerRow, childCount);
        if (actualItemsPerRow <= 0) actualItemsPerRow = 1;

        // 计算网格参数
        int availableWidth = width - paddingLeft - paddingRight;
        GridLayoutParams gridParams = calculateGridParams(availableWidth, actualItemsPerRow);
        int itemWidthPx = gridParams.itemWidth;
        int marginLeftPx = gridParams.marginLeft;
        int marginRightPx = gridParams.marginRight;

        int currentTop = paddingTop;
        int currentRowHeight = 0;
        int currentRowItemCount = 0;

        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            if (child.getVisibility() == GONE) {
                continue;
            }

            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            int rowIndex = currentRowItemCount;

            // 计算水平位置
            int itemTotalWidth = itemWidthPx + marginLeftPx + marginRightPx;
            int baseLeft = paddingLeft + rowIndex * itemTotalWidth + marginLeftPx;
            int childLeft = baseLeft;

            // 垂直位置（居中显示）
            int childTop = currentTop + lp.topMargin;
            int childHeight = child.getMeasuredHeight();

            // 布局子View
            child.layout(childLeft, childTop,
                    childLeft + child.getMeasuredWidth(), childTop + childHeight);

            // 更新行高
            int childHeightWithMargin = childHeight + lp.topMargin + lp.bottomMargin;
            currentRowHeight = Math.max(currentRowHeight, childHeightWithMargin);
            currentRowItemCount++;

            // 换行处理
            if (currentRowItemCount == actualItemsPerRow || i == childCount - 1) {
                currentTop += currentRowHeight;
                if (i < childCount - 1) { // 最后一行不加行间距
                    currentTop += mRowSpacing;
                }
                currentRowHeight = 0;
                currentRowItemCount = 0;
            }
        }
    }

    // ========== LayoutParams相关 ==========
    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    }

    @Override
    protected LayoutParams generateLayoutParams(LayoutParams p) {
        return new MarginLayoutParams(p);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    @Override
    protected boolean checkLayoutParams(LayoutParams p) {
        return p instanceof MarginLayoutParams;
    }

    // ========== 公共方法 ==========
    public void setItemsPerRow(int itemsPerRow) {
        if (itemsPerRow < 0) return;
        this.mItemsPerRow = itemsPerRow;
        requestLayout();
    }

    public int getItemsPerRow() {
        return mItemsPerRow;
    }

    public void setMarginMode(@MarginMode int marginMode) {
        this.mMarginMode = marginMode;
        requestLayout();
    }

    @MarginMode
    public int getMarginMode() {
        return mMarginMode;
    }

    public void setItemMarginLeft(float marginLeft) {
        this.mItemMarginLeft = marginLeft;
        requestLayout();
    }

    public void setItemMarginRight(float marginRight) {
        this.mItemMarginRight = marginRight;
        requestLayout();
    }

    public void setRowSpacing(float rowSpacing) {
        this.mRowSpacing = rowSpacing;
        requestLayout();
    }

    public float getRowSpacing() {
        return mRowSpacing;
    }

    // ========== 内部辅助类 ==========

    /**
     * 网格布局参数
     */
    private static class GridLayoutParams {
        final int itemWidth;
        final int marginLeft;
        final int marginRight;

        GridLayoutParams(int itemWidth, int marginLeft, int marginRight) {
            this.itemWidth = itemWidth;
            this.marginLeft = marginLeft;
            this.marginRight = marginRight;
        }
    }

    /**
     * 测量规格
     */
    private static class MeasureSpecs {
        final int widthSpec;
        final int heightSpec;

        MeasureSpecs(int widthSpec, int heightSpec) {
            this.widthSpec = widthSpec;
            this.heightSpec = heightSpec;
        }
    }
}